package com.example.websocket.listener;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionConnectedEvent;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Component
public class OnlineUserTracker {

    private final Set<String> onlineUsers = ConcurrentHashMap.newKeySet();
    private final Map<String, Set<String>> groupMembers = new ConcurrentHashMap<>();
    private final SimpMessagingTemplate messagingTemplate;

    @Autowired
    public OnlineUserTracker(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    // 关于 IOC 容易事件的使用参考 https://docs.springjava.cn/spring-framework/reference/core/beans/context-introduction.html#context-functionality-events

    // 监听 WebSocket 连接事件
    @EventListener
    public void handleWebSocketConnectListener(SessionConnectedEvent event) {
        System.out.println("WebSocket 连接事件");
        StompHeaderAccessor headers = StompHeaderAccessor.wrap(event.getMessage());
        String username = getUsernameFromHeaders(headers);
        if (username != null && !onlineUsers.contains(username)) {
            onlineUsers.add(username);
            broadcastOnlineUsers();
        }
    }

    // 监听 WebSocket 断开连接事件
    @EventListener
    public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
        System.out.println("WebSocket 断开连接事件");
        StompHeaderAccessor headers = StompHeaderAccessor.wrap(event.getMessage());
        String username = getUsernameFromHeaders(headers);
        if (username != null && onlineUsers.contains(username)) {
            onlineUsers.remove(username);
            broadcastOnlineUsers();
        }
    }

    private String getUsernameFromHeaders(StompHeaderAccessor headers) {
        // 假设用户名存储在会话属性中
        return (String) Objects.requireNonNull(headers.getSessionAttributes()).get("username");
    }

    private void broadcastOnlineUsers() {
        // 广播更新后的在线用户列表给所有客户端
        messagingTemplate.convertAndSend("/topic/online-users", onlineUsers);
    }




    // 当用户加入群聊时调用此方法
    public void joinGroup(String groupId, String username) {
        groupMembers.computeIfAbsent(groupId, k -> ConcurrentHashMap.newKeySet()).add(username);
        broadcastGroupStatus(groupId);
    }

    // 当用户退出群聊时调用此方法
    public void leaveGroup(String groupId, String username) {
        Set<String> members = groupMembers.get(groupId);
        if (members != null && members.contains(username)) {
            members.remove(username);
            broadcastGroupStatus(groupId);
        }
    }

    // 广播群聊状态变化（例如在线人数）
    private void broadcastGroupStatus(String groupId) {
        Set<String> onlineMembers = getOnlineMembersInGroup(groupId);
        messagingTemplate.convertAndSend("/topic/group-status/" + groupId, onlineMembers);
    }

    // 获取指定群聊中的在线成员
    private Set<String> getOnlineMembersInGroup(String groupId) {
        return groupMembers.getOrDefault(groupId, Collections.emptySet())
                .stream()
                .filter(onlineUsers::contains)
                .collect(Collectors.toSet());
    }

}


// 关于 WebSocket 中的一系列时间参考官方文档 https://springdoc.cn/spring/web.html#websocket-stomp-application-context-events